package main

import (
	"context"
	"errors"
	"fmt"
	"github.com/aws/smithy-go"
	"log"
	"os"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
	// MinIO配置信息 - 请替换为你的实际配置
	endpoint := "http://58.49.94.131:18380"
	accessKeyID := "yangmf"
	secretAccessKey := "159357aa"
	bucketName := "ephpre"
	localFilePath := "D:\\raw\\logo.png"
	objectKey := "logo.png"
	downloadPath := "logo.png"

	// 配置自定义解析器以连接到MinIO
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		return aws.Endpoint{
			URL:               endpoint,
			HostnameImmutable: true,
			SigningRegion:     "us-east-1", // MinIO通常使用us-east-1作为签名区域
		}, nil
	})

	// 加载AWS配置
	cfg, err := config.LoadDefaultConfig(context.TODO(),
		config.WithRegion("us-east-1"),
		config.WithEndpointResolverWithOptions(customResolver),
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
			accessKeyID,
			secretAccessKey,
			"",
		)),
	)
	if err != nil {
		log.Fatalf("无法加载配置: %v", err)
	}

	// 创建S3客户端
	client := s3.NewFromConfig(cfg)

	// 检查存储桶是否存在，不存在则创建
	exists, err := bucketExists(client, bucketName)
	if err != nil {
		log.Fatalf("检查存储桶失败: %v", err)
	}

	if !exists {
		_, err := client.CreateBucket(context.TODO(), &s3.CreateBucketInput{
			Bucket: aws.String(bucketName),
		})
		if err != nil {
			log.Fatalf("创建存储桶失败: %v", err)
		}
		fmt.Printf("存储桶 '%s' 创建成功\n", bucketName)
	} else {
		fmt.Printf("存储桶 '%s' 已存在\n", bucketName)
	}

	// 上传文件
	file, err := os.Open(localFilePath)
	if err != nil {
		log.Fatalf("无法打开本地文件: %v", err)
	}
	defer file.Close()

	_, err = client.PutObject(context.TODO(), &s3.PutObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
		Body:   file,
	})
	if err != nil {
		log.Fatalf("文件上传失败: %v", err)
	}
	fmt.Printf("文件 '%s' 上传到 '%s/%s' 成功\n", localFilePath, bucketName, objectKey)

	// 列出存储桶中的对象
	listObjects, err := client.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{
		Bucket: aws.String(bucketName),
	})
	if err != nil {
		log.Fatalf("列出对象失败: %v", err)
	}

	fmt.Printf("存储桶 '%s' 中的对象:\n", bucketName)
	for _, obj := range listObjects.Contents {
		fmt.Printf(" - %s (大小: %d bytes, 最后修改: %s)\n",
			*obj.Key, *obj.Size, obj.LastModified.Format("2006-01-02 15:04:05"))
	}

	// 下载文件
	output, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		log.Fatalf("获取对象失败: %v", err)
	}
	defer output.Body.Close()

	// 将下载内容写入本地文件
	outFile, err := os.Create(downloadPath)
	if err != nil {
		log.Fatalf("创建下载文件失败: %v", err)
	}
	defer outFile.Close()

	// 复制内容
	_, err = outFile.ReadFrom(output.Body)
	if err != nil {
		log.Fatalf("写入下载文件失败: %v", err)
	}
	fmt.Printf("文件下载到 '%s' 成功\n", downloadPath)

	//// 删除对象
	//_, err = client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{
	//	Bucket: aws.String(bucketName),
	//	Key:    aws.String(objectKey),
	//})
	//if err != nil {
	//	log.Fatalf("删除对象失败: %v", err)
	//}
	//fmt.Printf("对象 '%s/%s' 删除成功\n", bucketName, objectKey)
}

// 检查存储桶是否存在
func bucketExists(client *s3.Client, bucketName string) (bool, error) {
	_, err := client.HeadBucket(context.TODO(), &s3.HeadBucketInput{
		Bucket: aws.String(bucketName),
	})
	if err != nil {
		var apiErr smithy.APIError
		if errors.As(err, &apiErr) {
			switch apiErr.ErrorCode() {
			case "NotFound":
				return false, nil
			default:
				return false, err
			}
		}
		return false, err
	}
	return true, nil
}
